﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.ServiceModel;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
namespace SXDSVC3
{
    public interface IWCFService<TDependency>
    {
        TDependency Dependency { get; set; }
    }

    public abstract class WCFServiceBase<IChannel, Channel, TDependency> : IDisposable
        where Channel : IWCFService<TDependency>, new()
    {
        private readonly System.Threading.AutoResetEvent _waitor = new System.Threading.AutoResetEvent(false);        
        private readonly object _locker = new object();
        private bool _isOpen;
        protected abstract string Url { get; }
        protected abstract TDependency Dependency { get; }
        public bool IsOpen
        {
            get
            {
                lock (_locker)
                {
                    return _isOpen;
                }
            }
            private set
            {
                lock (_locker)
                {
                    _isOpen = value;
                }
            }
        }

        public void Open()
        {
            System.Threading.ThreadPool.QueueUserWorkItem(o =>
            {
                var namePipeAddress = new Uri(Url);
                var serverType = typeof(Channel);
                using (var host = new WCFServiceHost<Channel, TDependency>(Dependency, serverType, namePipeAddress))
                {
                    var serverInterfaceType = typeof(IChannel);
                    var namePipeBiding = new NetNamedPipeBinding();
                    host.AddServiceEndpoint(serverInterfaceType, namePipeBiding, "");
                    host.Open();
                    IsOpen = true;
                    OnOpen();
                    _waitor.WaitOne();
                    host.Close();
                    IsOpen = false;
                }
            });
        }

        public void Close()
        {
            Dispose();
        }
        protected virtual void OnOpen()
        {

        }
        #region IDisposeable
        private bool disposed;
        ~WCFServiceBase()
        {
            Dispose(false);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            if (disposed)
            {
                return;
            }
            if (disposing)
            {
                // 清理托管资源
            }
            // 清理非托管资源
            _waitor.Set();
            disposed = true;
        }
        #endregion IDisposeable

    }
    public class WCFInstanceProvider<Service, TDependency> : IInstanceProvider, IContractBehavior
        where Service : IWCFService<TDependency>, new()
    {
        private readonly TDependency _dependency;
        public WCFInstanceProvider(TDependency dependency)
        {
            if (dependency == null)
            {
                throw new ArgumentNullException("dependency");
            }
            _dependency = dependency;
        }
        #region IInstanceProvider Members
        public object GetInstance(InstanceContext instanceContext, Message message)
        {
            return GetInstance(instanceContext);
        }
        public object GetInstance(InstanceContext instanceContext)
        {
            return new Service { Dependency = _dependency };
        }

        public void ReleaseInstance(InstanceContext instanceContext, object instance)
        {
        }

        #endregion
        #region IContractBehavior Members        
        public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
            
        }
        public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {

        }
        public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
        {

            dispatchRuntime.InstanceProvider = this;

        }
        public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
        {

        }
        #endregion
    }
    public class WCFServiceHost<Service, TDependency> : ServiceHost
        where Service : IWCFService<TDependency>, new()
    {

        public WCFServiceHost(TDependency dependency, Type serviceType, params Uri[] baseAddresses)

            : base(serviceType, baseAddresses)
        {

            if (dependency == null)
            {

                throw new ArgumentNullException("dependency");

            }



            foreach (var cd in ImplementedContracts.Values)
            {

                cd.Behaviors.Add(new WCFInstanceProvider<Service, TDependency>(dependency));

            }

        }

    }
}
